package com.salt.modules.sys.web;

import com.google.common.collect.Lists;
import com.salt.common.json.AjaxJson;
import com.salt.common.utils.StringUtils;
import com.salt.core.log.annotation.OperationRecord;
import com.salt.core.web.BaseController;
import com.salt.modules.sys.entity.*;
import com.salt.modules.sys.service.*;
import com.salt.modules.sys.utils.MenuUtils;
import com.salt.modules.sys.utils.UserUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 菜单Controller
 * @author salt
 * @version 2016-3-23
 */

@RestController
@RequestMapping("/sys/menu")
public class MenuController extends BaseController {

    @Autowired
    private MenuService menuService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private AppMenuService appMenuService;
    @Autowired
    private OfficeService officeService;
    @Autowired
    private MultiTenantService multiTenantService;

    @ModelAttribute("menu")
    public Menu get(@RequestParam(required = false) String id) {
        if (StringUtils.isNotBlank(id)) {
            return menuService.get(id);
        } else {
            return new Menu();
        }
    }

    @PostMapping("insert")
    @OperationRecord(service = "系统服务", module = "菜单管理", operation = "新增", description = "")
    public void insert(Menu menu){
        // 添加租户ID
        // 当前用户是超级管理员，则菜单的租户ID标识已在前端添加，
        // 当前用户不是超级管理员，则菜单的租户ID标识取所属公司ID
        User user = UserUtils.getUser();
        if (!"1".equals(user.getId())) {
            menu.setTenant(user.getCompany().getId());
        }
        menuService.saveMenu(menu);
    }

    @GetMapping("findAll")
    public List<Menu> findAllMenu(Menu menu){
        return menuService.findAllMenu(menu);
    }

    @GetMapping("searchMenu")
    public List<Menu> searchMenu(Menu menu) {
        if (StringUtils.isBlank(menu.getTenant())) {
            User user = UserUtils.getUser();
            if (user.isAdmin()) { // 是不是超级管理员
                // 暂时不能删除
                //List<Office> tenantList = officeService.getUserableChildren("0");
                //menu.setTenant(tenantList.get(0).getId());
            } else {
                menu.setTenant(user.getCompany().getId());
            }
        }
        if (StringUtils.isBlank(menu.getClient())) {
            menu.setClient("2");
        }
        return menuService.searchMenu(menu);
    }

    /**
     * mac 版应用商店
     * @return
     */
    @GetMapping("getAllMenuList")
    public AjaxJson getAllMenuList(Office office) {
        Map map = multiTenantService.getTenant(office);
        String tenant = (String) map.get("tenant");
        List<String> tenantIds = (List<String>) map.get("tenantIds");
        List<Menu> allMenuList = MenuUtils.getAllMenuList(new Menu(tenant, tenantIds, "2"));
        // 是否已下载
        AppMenu appMenu = new AppMenu(UserUtils.getUser().getId());
        appMenu.setTenant(tenant);
        List<AppMenu> appMenuList = appMenuService.findList(appMenu);
        AppMenu defaultAppMenu = appMenuService.get("1");
        appMenuList.add(defaultAppMenu);
        for (Menu m:allMenuList) {
            for (AppMenu am:appMenuList) {
                if (m.getId().equals(am.getMenuId())) {
                    m.setIsDownload(1);
                    break;
                }
            }
        }
        // 是否有下载权限
        List<Menu> authMenuList = MenuUtils.getMenus(new Menu(tenant, tenantIds, "2"));
        for (Menu m:allMenuList) {
            for (Menu authMenu:authMenuList) {
                if (m.getId().equals(authMenu.getId())) {
                    m.setIsDownloadAuth(1);
                    break;
                }
            }
        }
        return AjaxJson.success().put("allMenuList", allMenuList);
    }

    @RequiresPermissions("sys:menu:list")
    @GetMapping("list")
    public AjaxJson list() {
         List<Menu> menus = Lists.newArrayList();
        for(Menu menu: menuService.findAllMenu(new Menu())){
            if(!"1".equals(menu.getId())){
                menus.add(menu);
            }
        }
        return AjaxJson.success().put("menuList", menus);
    }

    @RequiresPermissions(value = {"sys:menu:view", "sys:menu:add", "sys:menu:edit"}, logical = Logical.OR)
    @GetMapping("queryById")
    public AjaxJson queryById(Menu menu) {
        if (menu.getParent() == null || menu.getParent().getId() == null) {
            menu.setParent(new Menu(Menu.getRootId()));
        }
        menu.setParent(menuService.get(menu.getParent().getId()));
        return AjaxJson.success().put("menu", menu);
    }

    @RequiresPermissions(value = {"sys:menu:add", "sys:menu:edit"}, logical = Logical.OR)
    @PostMapping("save")
    @OperationRecord(service = "系统服务", module = "菜单管理", operation = "新增/修改", description = "")
    public AjaxJson save(Menu menu) {
        // 只有超级管理员和管理员(管理员只有对本公司的菜单具有操作权限)对菜单有操作权限
        // 暂时放开菜单操作权限，待后期项目稳定后加上，同时修改UserUtils里面的getMenuList()方法
        /*if (!UserUtils.getUser().isAdmin()) {
            return AjaxJson.error("越权操作，只有超级管理员才能添加或修改数据！");
        }*/
        if (saltProperites.isDemoMode()) {
            return AjaxJson.error("演示模式，不允许操作！");
        }
        /**
         * 后台hibernate-validation插件校验
         */
        String errMsg = beanValidator(menu);
        if (StringUtils.isNotBlank(errMsg)) {
            return AjaxJson.error(errMsg);
        }
        // 添加租户ID
        // 当前用户是超级管理员，则菜单的租户ID标识已在前端添加，
        // 当前用户不是超级管理员，则菜单的租户ID标识取所属公司ID
        User user = UserUtils.getUser();
        if (!user.isAdmin()) {
            menu.setTenant(user.getCompany().getId());
        }
        // 获取排序号，最末节点排序号+30
        if (StringUtils.isBlank(menu.getId())) {
            List<Menu> list = Lists.newArrayList();
            Menu m = new Menu();
            m.setTenant(menu.getTenant());
            m.setClient(menu.getClient());
            List<Menu> sourcelist = menuService.findAllMenu(m);
            Menu.sortList(list, sourcelist, menu.getParentId(), false);
            if (list.size() > 0) {
                menu.setSort(list.get(list.size() - 1).getSort() + 30);
            }
        }
        menuService.saveMenu(menu);

        return AjaxJson.success("保存成功!");
    }

    @RequiresPermissions("sys:menu:del")
    @DeleteMapping("delete")
    @OperationRecord(service = "系统服务", module = "菜单管理", operation = "删除", description = "")
    public AjaxJson delete(Menu menu) {
        // 只有超级管理员和管理员(管理员只有对本公司的菜单具有操作权限)对菜单有操作权限
        // 验证超级管理员和管理员的权限
        // 暂时放开菜单操作权限，待后期项目稳定后加上，同时修改UserUtils里面的getMenuList()方法
        /*boolean flag = false;
        User user = UserUtils.getUser();
        if (user.isAdmin()) {
            flag = true;
            //return AjaxJson.error("越权操作，只有管理员才能删除数据！");
        }
        if (AdminUtils.isAdmin()) {
            if (menu.getTenant().equals(user.getCompany().getId())) {
                flag = true;
                //return AjaxJson.error("越权操作，只有超级管理员才能删除数据！");
            } else {
                flag = false;
            }
        }
        if (flag) {

        }*/


        AjaxJson j = new AjaxJson();
        if (saltProperites.isDemoMode()) {
            return AjaxJson.error("演示模式，不允许操作");
        }
        menuService.delete(menu);
        return AjaxJson.success("删除成功!");
    }


    /**
     * 修改菜单排序
     */
    @RequiresPermissions("sys:menu:updateSort")
    @PostMapping("sort")
    public AjaxJson sort(String id1, int sort1, String id2, int sort2) {
        AjaxJson j = new AjaxJson();
        if (saltProperites.isDemoMode()) {
            return AjaxJson.error("演示模式，不允许操作！");
        }
        Menu menu = new Menu();
        menu.setId(id1);
        menu.setSort(sort1);
        menuService.updateSort(menu);
        menu.setId(id2);
        menu.setSort(sort2);
        menuService.updateSort(menu);
        return AjaxJson.success("排序成功！");
    }

    @GetMapping("getChildren")
    public List<Menu> getChildren(String parentId) {
        if ("-1".equals(parentId)) {
            parentId = "1";
        }
        return menuService.getChildren(parentId);
    }


    public List<Menu> getTreeMenu(List<Menu> list, String roleId, String extId, String isShowHid) {
        List rootTree = Lists.newArrayList();
        Menu menu = menuService.get("1");
        getChildOfTree(menu, list, extId, isShowHid);
        rootTree.add(menu);
        return rootTree;
    }

    private Menu getChildOfTree(Menu menuItem, List<Menu> menuList, String extId, String isShowHide) {
        menuItem.setChildren(Lists.newArrayList());
        for (Menu child : menuList) {
            if (StringUtils.isBlank(extId) || (extId != null && !extId.equals(child.getId()) && child.getParentIds().indexOf("," + extId + ",") == -1)) {
                /*if (isShowHide != null && isShowHide.equals("0") && child.getIsShow().equals("0")) {
                    continue;
                }*/
                if (StringUtils.isNotBlank(isShowHide) && !Objects.equals(isShowHide, child.getIsShow())) {
                    continue;
                }
                if (child.getParentId().equals(menuItem.getId())) {
                    menuItem.getChildren().add(getChildOfTree(child, menuList, extId, isShowHide));
                }
            }
        }
        return menuItem;
    }

    /**
     * isShowHide是否显示隐藏菜单
     *
     * @param extId
     * @return
     */
    @RequiresPermissions("user")
    @GetMapping("treeData")
    public AjaxJson treeData(Menu menu, @RequestParam(required = false) String roleId, @RequestParam(required = false) String extId, @RequestParam(required = false) String isShowHide) {
        if (StringUtils.isBlank(menu.getTenant())) {
            User user = UserUtils.getUser();
            if (user.isAdmin()) { // 是不是超级管理员
                // 暂时不能删除
                //List<Office> tenantList = officeService.getUserableChildren("0");
                //menu.setTenant(tenantList.get(0).getId());
            } else {
                menu.setTenant(user.getCompany().getId());
            }
        }
        if (StringUtils.isBlank(menu.getClient())) {
            menu.setClient("2");
        }
        List<Menu> list = menuService.findAllMenu(menu);
        List rootTree = getTreeMenu(list, roleId, extId, isShowHide);
        Role role = roleService.get(roleId);
        String menuIds = "";
        if (role != null) {
            menuIds = "," + role.getMenuIds() + ",";
        }
        return AjaxJson.success().put("treeData", rootTree).put("selected", menuIds);
    }

    /**
     * isShowHide是否显示隐藏菜单
     *
     * @return
     */
    @RequiresPermissions("user")
    @GetMapping("treeData2")
    public AjaxJson treeData2(Menu menu) {
        if (StringUtils.isBlank(menu.getTenant())) {
            User user = UserUtils.getUser();
            if (user.isAdmin()) { // 是不是超级管理员
                //List<Office> tenantList = officeService.getUserableChildren("0");
                //menu.setTenant(tenantList.get(0).getId());
            } else {
                menu.setTenant(user.getCompany().getId());
            }
        }
        if (StringUtils.isBlank(menu.getClient())) {
            menu.setClient("2");
        }
        List<Menu> list = menuService.findAllMenu(menu);
        List<Menu> rootTree = getTreeMenu(list, "", "", "");
        return AjaxJson.success().put("treeData", rootTree.get(0).getChildren());
    }

    /**
     * isShowHide是否显示隐藏菜单
     *
     * @return
     */
    @RequiresPermissions("user")
    @GetMapping("treeData3")
    public AjaxJson treeData3(Menu menu) {
        if (StringUtils.isBlank(menu.getTenant())) {
            User user = UserUtils.getUser();
            if (user.isAdmin()) { // 是不是超级管理员
                //List<Office> tenantList = officeService.getUserableChildren("0");
                //menu.setTenant(tenantList.get(0).getId());
            } else {
                menu.setTenant(user.getCompany().getId());
            }
        }
        if (StringUtils.isBlank(menu.getClient())) {
            menu.setClient("2");
        }
        menu.setType(null);
        List<Menu> list = menuService.findAllMenu(menu);
        List<Menu> rootTree = getTreeMenu3(getTreeMenu(list, "", "", "").get(0).getChildren());
        return AjaxJson.success().put("treeData", rootTree);
    }

    private List<Menu> getTreeMenu3(List<Menu> list) {
        Map<String,List<Menu>> map = new LinkedHashMap();
        List<Menu> firstList = new ArrayList<>();
        getAllMenu(list, map, firstList);

        for (Menu menu : firstList) {
            menu.setChildren(map.get(menu.getId()));
        }

        return firstList;
    }

    private void getAllMenu(List<Menu> list, Map<String, List<Menu>> map,  List<Menu> firstList){
        String[] parentIds = null;
        /*list = list.stream().sorted(Comparator.comparing(Menu::getSort))
                .collect(Collectors.toList());*/

        if (list != null) {
            for (Menu menu : list) {

                /*if(StringUtils.isBlank(menu.getIsShow()) || menu.getIsShow().equals("0")){
                    continue;
                }*/

                if(menu.getChildren() != null && menu.getChildren().size() > 0){
                    getAllMenu(menu.getChildren(), map, firstList);
                }

                menu.setChildren(null);


                if(StringUtils.isNotBlank(menu.getType()) && menu.getType().equals("1")){
                    parentIds = menu.getParentIds().split(",");
                    if(parentIds.length >= 3){
                        List<Menu> menuList = map.get(parentIds[2]);

                        if(menuList == null){
                            menuList = new ArrayList<>();
                        }

                        menuList.add(menu);

                        map.put(parentIds[2], menuList);
                    }
                }

                if(StringUtils.isNotBlank(menu.getParentId()) && menu.getParentId().equals("1")){
                    firstList.add(menu);
                }

            }
        }
    }


    /**
     * isShowHide是否显示隐藏菜单
     *
     * @return
     */
    @RequiresPermissions("user")
    @GetMapping("treeData4")
    public AjaxJson treeData4(Menu menu, @RequestParam("isShowHid") String isShowHid) {
        if (StringUtils.isBlank(menu.getTenant())) {
            User user = UserUtils.getUser();
            if (user.isAdmin()) { // 是不是超级管理员
                //List<Office> tenantList = officeService.getUserableChildren("0");
                //menu.setTenant(tenantList.get(0).getId());
            } else {
                menu.setTenant(user.getCompany().getId());
            }
        }
        if (StringUtils.isBlank(menu.getClient())) {
            menu.setClient("2");
        }
        List<Menu> list = menuService.findAllMenu(menu);
        List<Menu> rootTree = getTreeMenu4(getTreeMenu(list, "", "", isShowHid).get(0).getChildren());
        return AjaxJson.success().put("treeData", rootTree);
    }

    private Menu getChildOfTree4(Menu menuItem, List<Menu> menuList, String extId, String isShowHide) {
        menuItem.setChildren(Lists.newArrayList());
        for (Menu child : menuList) {
            if (StringUtils.isBlank(extId) || (extId != null && !extId.equals(child.getId()) && child.getParentIds().indexOf("," + extId + ",") == -1)) {
                /*if (isShowHide != null && isShowHide.equals("0") && child.getIsShow().equals("0")) {
                    continue;
                }*/
                if (!Objects.equals(isShowHide, child.getIsShow())) {
                    continue;
                }
                if (child.getParentId().equals(menuItem.getId())) {
                    menuItem.getChildren().add(getChildOfTree(child, menuList, extId, isShowHide));
                }
            }
        }
        return menuItem;
    }

    private List<Menu> getTreeMenu4(List<Menu> list) {
        List<Menu> returnList = null;
        if (list != null) {
            for (Menu menu : list) {
                if (menu.getChildren() != null) {
                    for (Menu child : menu.getChildren()) {
                        returnList = new ArrayList<>();
                        child.setChildren(packageData(child.getChildren(), returnList));
                    }
                }
            }
        }

        return list;
    }

    private List<Menu> packageData(List<Menu> list, List<Menu> returnList){
        if(list == null){
            return null;
        }

        for (Menu menu : list) {
            if(menu.getChildren() == null || menu.getChildren().size() == 0){
                returnList.add(menu);
            } else {
                packageData(menu.getChildren(), returnList);
            }
        }

        return returnList;
    }

}
